/**
 * 
 */
package demo.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author roger.xu
 * 
 */
public class BaseUtils {
    private static final Log _log = LogFactory.getLog(BaseUtils.class.getSimpleName());

    public static final String NEW_LINE = System.getProperty("line.separator");

    private static final String PROPERTIES_CLASSPATH = "test.properties";
    private static final Properties properties = new Properties();
    private static final Console console = Console.getInstance();

    public static Console getConsole() {
        return console;
    }

    public static void loadProperties() {
        try {
            InputStream in = BaseUtils.class.getClassLoader().getResourceAsStream(PROPERTIES_CLASSPATH);
            properties.load(in);

            // override properties
            final String propertiesFileName = properties.getProperty("properties.name");
            if (propertiesFileName != null) {
                in = BaseUtils.class.getClassLoader().getResourceAsStream(propertiesFileName);
                properties.load(in);
            }
        } catch (IOException e) {
            _log.error(e.getMessage(), e);
        }
    }

    /**
     * Get the property with the specified key. The method returns null if the property is not found.
     * 
     * @param key
     *            the property key.
     * @return the value with the specified key value.
     */
    public static String getProperty(final String key) {
        return properties.getProperty(key);
    }

    /**
     * Cast the object with the specified type.
     * 
     * @param <T>
     *            The cast type.
     * @param obj
     *            the object to cast.
     * @return The cast object. null if failed to cast.
     */
    @SuppressWarnings("unchecked")
    public static <T> T cast(final Object obj) {
        T value = null;

        if (obj != null) {
            try {
                value = (T) obj;
            } catch (ClassCastException e) {
                _log.warn("[CastException]", e);
            }
        }

        return value;
    }

    /**
     * Join the provided arguments into a single String with a space as the separator.
     * 
     * @param args
     *            the array of values to join together.
     * @return the joined String.
     */
    public static String join(final Object... args) {
        return StringUtils.join(args, " ");
    }

    /**
     * Concatenate the provided arguments into a single String.
     * 
     * @param args
     *            the array of values to join together.
     * @return the concatenated String.
     */
    public static String concat(final Object... args) {
        return StringUtils.join(args);
    }

    /**
     * Get the current timestamp mark.
     * 
     * @return the timestamp mark of current time.
     */
    public static String getTimestamp() {
        final long currentTimeMillis = System.currentTimeMillis();
        final String timestamp = DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(currentTimeMillis);
        final String mark = String.format("[%s]", timestamp);

        return mark;
    }

    /**
     * Extract string from input.
     * 
     * @param input
     * @param regexp
     * @return
     */
    public static String extractString(final String input, final String regexp) {
        String result = null;
        final Pattern pattern = Pattern.compile(regexp, Pattern.CASE_INSENSITIVE);
        final Matcher matcher = pattern.matcher(input);
        while (matcher.find()) { // find() must be called before fetch group
            if (matcher.groupCount() > 0) {
                result = matcher.group(1); // group index starts from 1
            }
        }

        return result;
    }
}
